package com.xms.schema.service.entity;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xms.core.exception.XmsException;
import com.xms.datacore.service.UpdaterService;
import com.xms.event.core.AuthorizationStateChangedEvent;
import com.xms.event.core.IEventPublisher;
import com.xms.schema.core.EntityDefaults;
import com.xms.schema.core.EntityMask;
import com.xms.schema.entity.Entity;
import com.xms.schema.service.attribute.IAttributeCreaterService;
import com.xms.utils.CollectionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * EntityUpdaterService
 * </p>
 *
 * @author migo
 * @since 2021/9/2
 */
@CacheConfig(cacheNames = "schema.entity", keyGenerator = "CacheKeyGenerator")
@Service
public class EntityUpdaterService extends UpdaterService<Entity> implements IEntityUpdaterService {
    private IEventPublisher _eventPublisher;
    private IAttributeCreaterService _attributeCreaterService;

    @Autowired
    public void EntityUpdaterService(IAttributeCreaterService attributeCreaterService,
                                     IEventPublisher eventPublisher) {
        _attributeCreaterService = attributeCreaterService;
        _eventPublisher = eventPublisher;
    }

    @CacheEvict(allEntries = true, condition = "#result == true")
    @Override
    @Transactional(rollbackFor=Exception.class)
    public boolean update(Entity entity) throws XmsException, SQLException {
        Entity oldEntity = super.getById(entity.getEntityid());
        if (oldEntity == null) {
            return false;
        }
        if (!oldEntity.getIscustomizable()) {
            entity.setAuthorizationenabled(oldEntity.getAuthorizationenabled());
            entity.setWorkflowenabled(oldEntity.getWorkflowenabled());
            entity.setEntitymask(oldEntity.getEntitymask());
        }
        boolean success = super.update(entity);
        if(success) {
            //从组织范围改成用户范围
            if (oldEntity.getEntitymask() != entity.getEntitymask() && entity.getEntitymask() == EntityMask.User.value()) {
                //创建所有者字段
                _attributeCreaterService.createOwnerAttributes(entity);
            }
            //启用审批流，创建相关字段
            if (!oldEntity.getWorkflowenabled() && entity.getWorkflowenabled()) {
                _attributeCreaterService.createWorkFlowAttributes(entity);
            }
            //权限状态更改
            if(entity.getAuthorizationenabled() != oldEntity.getAuthorizationenabled()){
                _eventPublisher.publish(new AuthorizationStateChangedEvent(EntityDefaults.MODULE_NAME, Collections.singletonList(entity.getEntityid()), entity.getAuthorizationenabled()));
            }
        }
        return success;
    }

    @CacheEvict(allEntries = true, condition = "#result == true")
    @Transactional(rollbackFor=Exception.class)
    @Override
    public boolean updateAuthorization(boolean isAuthorization, List<UUID> id) {
        Assert.notEmpty(id, "id must not be empty");
        boolean success = super.update(new LambdaUpdateWrapper<Entity>()
                .set(Entity::getAuthorizationenabled, isAuthorization)
                .in(Entity::getEntityid, id));
        if (success) {
            _eventPublisher.publish(new AuthorizationStateChangedEvent(EntityDefaults.MODULE_NAME, id, isAuthorization));
        }
        return success;
    }

    @CacheEvict(allEntries = true, condition = "#result == true")
    @Transactional(rollbackFor=Exception.class)
    @Override
    public boolean updateLogEnabled(boolean state, List<UUID> id) {
        return super.update(new LambdaUpdateWrapper<Entity>()
                .in(Entity::getEntityid, id)
                .set(Entity::getLogenabled, state));
    }

    @CacheEvict(allEntries = true, condition = "#result == true")
    @Transactional(rollbackFor=Exception.class)
    @Override
    public boolean updateMany(List<Entity> entity) throws XmsException, SQLException {
        if (CollectionUtil.isEmpty(entity)) {
            return false;
        }
        for (Entity item : entity) {
            this.update(item);
        }
        return true;
    }

    @CacheEvict(allEntries = true, condition = "#result == true")
    @Transactional(rollbackFor=Exception.class)
    public boolean update(Wrapper<Entity> updateWrapper) {
        return super.update(updateWrapper);
    }

    @CacheEvict(allEntries = true, condition = "#result == true")
    @Transactional(rollbackFor=Exception.class)
    public boolean update(Entity entity, Wrapper<Entity> updateWrapper) {
        return super.update(entity, updateWrapper);
    }
}
